package cn.kgc.thread.demo3;


import java.util.Random;
import java.util.concurrent.*;

/**
 * <p>添加描述信息</p>
 *
 * @author 卢传琪
 */
public class Demo1 {
    private static ThreadPoolExecutor executor=new ThreadPoolExecutor(
            5,10,60,TimeUnit.SECONDS,
            new ArrayBlockingQueue<>(10),
            Executors.defaultThreadFactory(),
            new ThreadPoolExecutor.DiscardOldestPolicy());

    //thenApplyAsync:入参只能传入任务一的返回值
    //handleAsync:入参可以传入任务一的返回值，也可以传入任务一的异常

    //thenAcceptAsync:
    //thenApplyAsync:无返回结果

    //thenCombineAsync
    //thenAcceptBothAsync 前面的两个任务执行完了，没有返回值
    public static void main(String[] args) throws Exception {
        CompletableFuture<String> completableFuture1 =CompletableFuture.supplyAsync(() -> {
            System.out.println("执行任务1中的内容");
            try {
                Thread.sleep(15000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("任务1执行完毕");
            return "任务1的返回值";
        }, executor);

        CompletableFuture<String> completableFuture2 =CompletableFuture.supplyAsync(() -> {
            System.out.println("执行任务2中的内容");
            try {
                Thread.sleep(11000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("任务2执行完毕");
            return "任务2的返回值";
        }, executor);

        /*CompletableFuture.allOf(completableFuture1,completableFuture2).join();
        System.out.println("等待任务一和任务二都执行完毕以后在执行");*/
        CompletableFuture.anyOf(completableFuture1,completableFuture2).join();
        System.out.println("等待任务一和任务二中的任意一个执行完毕以后在执行");
    }

    private static void method8() throws InterruptedException, ExecutionException {
        CompletableFuture<String> completableFuture1 =CompletableFuture.supplyAsync(() -> {
            System.out.println("执行任务1中的内容");
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "任务1的返回值";
        }, executor);

        CompletableFuture<String> completableFuture2 =CompletableFuture.supplyAsync(() -> {
            System.out.println("执行任务2中的内容");
            try {
                Thread.sleep(6000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "任务2的返回值";
        }, executor);

        CompletableFuture<String> completableFuture3=
                completableFuture1.applyToEitherAsync(completableFuture2, result1 -> {
            System.out.println("执行任务三中的内容");
            System.out.println("任务1和任务2中有一个执行完了，返回值是:"+result1);
            return "任务三的返回值";
        }, executor);
        System.out.println("任务三的返回值"+completableFuture3.get());

        CompletableFuture<Void> completableFuture4=
        completableFuture1.acceptEitherAsync(completableFuture2, result1 -> {
            System.out.println("执行任务四中的内容");
            System.out.println("任务1和任务2中有一个执行完了，返回值是:"+result1);
        }, executor);

        completableFuture1.runAfterEitherAsync(completableFuture2, () -> {
            System.out.println("执行任务五中的内容");
        }, executor);
    }

    private static void method7() throws InterruptedException, ExecutionException {
        CompletableFuture<String> completableFuture1 =CompletableFuture.supplyAsync(() -> {
            System.out.println("执行任务一中的内容");
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "任务1的返回值";
        }, executor);

        CompletableFuture<String> completableFuture2 =CompletableFuture.supplyAsync(() -> {
            System.out.println("执行任务2中的内容");
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "任务2的返回值";
        }, executor);

        CompletableFuture<String> completableFuture3 = completableFuture1.thenCombineAsync(completableFuture2, (result1, result2) -> {
            System.out.println("执行任务3中的内容，需要等待任务一，任务二全部执行完毕以后在执行");
            System.out.println("在任务三中获取任务一和任务二的返回值是：" + result1 + "--" + result2);
            return "任务3的返回值";
        }, executor);
        System.out.println("最终任务三的返回结果是:"+completableFuture3.get());

        CompletableFuture<Void> completableFuture4=
                completableFuture1.thenAcceptBothAsync(completableFuture2, (result1, result2) -> {
            System.out.println("执行任务4中的内容，需要等待任务一，任务二全部执行完毕以后在执行");
            System.out.println("在任务四中获取任务一和任务二的返回值是：" + result1 + "--" + result2);
        }, executor);

        CompletableFuture<Void> completableFuture5=
        completableFuture1.runAfterBothAsync(completableFuture2,()->{
            System.out.println("任务一和任务二执行完毕以后，执行任务五");
        },executor);
    }

    private static void method6() {
        CompletableFuture.supplyAsync(() -> {
           System.out.println("执行任务一中的内容");
           return "任务1的返回值";
       }, executor).thenRunAsync(()->{
           System.out.println("执行任务2中的内容");
       });
    }

    private static void method5() {
        CompletableFuture<Void> completableFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println("执行任务一中的内容");
            return "任务1的返回值";
        }, executor).thenAcceptAsync((result)->{
            System.out.println("执行任务2中的内容，获得的任务1的返回值是"+result);
        });
    }

    private static void method4() throws InterruptedException, ExecutionException {
        CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println("执行任务一中的内容");
            return "任务1的返回值";
        }, executor).thenApplyAsync((result) -> {
            System.out.println("执行任务2中的内容，获得的任务1的返回值是：" + result);
            return "任务2的返回值";
        }, executor);
        System.out.println("最终获得返回值是"+completableFuture.get());
    }

    private static void method3() {
        CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务一开始执行");
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("任务一执行完毕");
            int result=5/0;
            return "任务一的返回值";
        }, executor).handleAsync((result,exception)->{
            System.out.println("任务二开始执行,任务二接收的任务一的返回值为:"+result);
            return "任务二的返回值";
        },executor);
    }

    private static void method2() throws InterruptedException, ExecutionException {
        // 任务2要求在任务1执行完成以后执行，并且任务2要使用任务1的返回值
        CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(() -> {
            String name = Thread.currentThread().getName();
            System.out.println(name + "任务开始执行");
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            int result=5/0;
            System.out.println(name + "任务执行完毕");
            return "任务1返回的结果";
        }, executor).whenCompleteAsync((result, exception) -> {
            //int temp = 5 / 0;
            System.out.println("执行任务二的操作,在任务二中获得任务一的返回值是:" + result);
        }, executor).exceptionally((exception) -> {
            System.out.println("任务中的异常信息" + exception.getMessage());
            return "异常处理后的返回值";
        });
        System.out.println(completableFuture.get());//任务一执行的结果
    }

    private static void method1() throws InterruptedException, ExecutionException {
        //completableFuture:异步编程
        CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println("线程池中执行的任务1");
            return "任务一执行的结果";
        }, executor);

        System.out.println(completableFuture.get());//任务一执行的结果

        //runAsync:没有返回值
        CompletableFuture<Void> completableFuture1 = CompletableFuture.runAsync(() -> {
            System.out.println("线程池中执行的任务2");
        }, executor);
        System.out.println(completableFuture1.get());//null
    }
}
